package com.ekuaitu.kuaitustaff.utils.ble.manager;

/**
 * Created by xiongjida on 2017/6/29.
 */

import android.bluetooth.BluetoothGattCharacteristic;
import android.os.Handler;
import android.os.Message;

import com.ekuaitu.kuaitustaff.utils.ble.ViseBluetooth;
import com.ekuaitu.kuaitustaff.utils.ble.bean.OrderCmd;
import com.ekuaitu.kuaitustaff.utils.ble.callback.data.ICharacteristicCallback;
import com.ekuaitu.kuaitustaff.utils.ble.exception.BleException;
import com.ekuaitu.kuaitustaff.utils.ble.helper.ICallBackCmd;
import com.ekuaitu.kuaitustaff.utils.ble.utils.ConvertUtil;
import com.ekuaitu.kuaitustaff.utils.ble.utils.HexUtil;
import com.ekuaitu.kuaitustaff.utils.ble.utils.Logger;

import java.util.concurrent.LinkedBlockingQueue;

/**
 * 管理蓝牙发送
 */
public class BLESendManager {

    private volatile static BLESendManager instance;

    private LinkedBlockingQueue<byte[]> dataSplitInfoQueue = new LinkedBlockingQueue<>();// 所有待发送的指令

    private LinkedBlockingQueue<byte[]> dataUnCompleteInfoQueue = new LinkedBlockingQueue<>();// 未完成发送的指令

    private int MSG_NORMAL_SEND = 1;

    private int MSG_REPEAT_SEND = 2;

    private int MSG_TIME_OUT = 3;

    private int MSG_TIME_OUT2 = 4;

    private final int DEFAULT_INTERVAL_TIME = 1000;// 重发间隔时间500ms

    private final int DEFAULT_INTERVAL_PER_BG_TIME = 2;//同一包数据的间隔时间

    private BluetoothGattCharacteristic mCharacteristic;

    private ICallBackCmd callBackCmd;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MSG_NORMAL_SEND) {
                send(msg.arg1, (OrderCmd) msg.obj);
            } else if (msg.what == MSG_REPEAT_SEND) {
                if (!dataUnCompleteInfoQueue.isEmpty() && dataUnCompleteInfoQueue.peek() != null) {
                    Logger.e("send", "重发：" + (((OrderCmd) msg.obj).getType().getCount() - msg.arg1));
                    primarySend(dataUnCompleteInfoQueue.peek(), msg.arg1, (OrderCmd) msg.obj);
                }
            } else if (msg.what == MSG_TIME_OUT) {
                // 十秒超时或者5秒超时（异步超时）
                reSet();
                if (callBackCmd != null) {
                    callBackCmd.onTimeOut((OrderCmd) msg.obj, 1);
                }
            } else if (msg.what == MSG_TIME_OUT2) {
                if (!dataUnCompleteInfoQueue.isEmpty()) {
                    // 超时无应答(同步超时)
                    Logger.e("dataCompleteInfoQueue_size", dataUnCompleteInfoQueue.size() + "");
                    reSet();
                    if (callBackCmd != null) {
                        callBackCmd.onTimeOut((OrderCmd) msg.obj, 2);
                    }
                }
            }
        }
    };

    public void setBluetoothGattCharacteristic(BluetoothGattCharacteristic mCharacteristic) {
        if (mCharacteristic == null) {
            throw new RuntimeException("参数不能为null");
        }
        this.mCharacteristic = mCharacteristic;
    }

    public void setCallBackCmd(ICallBackCmd callBackCmd) {
        if (callBackCmd == null) {
            throw new RuntimeException("参数不能为null");
        }
        this.callBackCmd = callBackCmd;
    }

    private BLESendManager() {
    }

    public static BLESendManager getInstance() {
        if (instance == null) {
            synchronized (BLESendManager.class) {
                if (instance == null) {
                    instance = new BLESendManager();
                }
            }
        }
        return instance;
    }

    /**
     * 发送BLE数据
     *
     * @param orderCmd
     */
    public synchronized void send(OrderCmd orderCmd) {
        send(orderCmd, false);
    }

    /**
     * @param orderCmd
     */
    public synchronized void send(OrderCmd orderCmd, boolean isRemoveOrperteTimeOut) {
        com.ekuaitu.kuaitustaff.utils.Logger.i("bleinfo-Helper", "发送指令" + orderCmd.getType().name());
        if (callBackCmd != null && isRemoveOrperteTimeOut) {
            callBackCmd.onStartSend();
        }
        dataUnCompleteInfoQueue.clear();
        if (orderCmd.getType().getCount() != 0) {
            Logger.e("设置发送数据超时时间：" + orderCmd.getType()
                    .getValue());
            handler.sendMessageDelayed(obtainMessage(MSG_TIME_OUT, 0, orderCmd), orderCmd.getType()
                    .getValue());
            dataUnCompleteInfoQueue.offer(orderCmd.getCmd());
        }
        primarySend(orderCmd.getCmd(), orderCmd.getType().getCount(), orderCmd);
    }

    private void primarySend(byte[] data, int times, OrderCmd orderCmd) {
        dataSplitInfoQueue.addAll(ConvertUtil.splitPacketFor20Byte(data));
        handler.sendMessage(obtainMessage(MSG_NORMAL_SEND, times, orderCmd));
    }

    /**
     * 生成message
     *
     * @param what
     * @param times    重试次数
     * @param orderCmd
     * @return
     */
    private Message obtainMessage(int what, int times, OrderCmd orderCmd) {
        Message message = Message.obtain();
        message.what = what;
        message.arg1 = times;
        message.obj = orderCmd;
        return message;
    }

    /**
     * @param times 重发次数
     */
    private void send(final int times, final OrderCmd orderCmd) {
        if (dataSplitInfoQueue != null && !dataSplitInfoQueue.isEmpty()) {
            if (dataSplitInfoQueue.peek() != null) {
                Logger.e("开始发送数据");
                ViseBluetooth.getInstance().writeCharacteristic(mCharacteristic,
                        dataSplitInfoQueue.poll(), new ICharacteristicCallback() {
                            @Override
                            public void onSuccess(byte[] characteristic) {
                                Logger.e("Send onSuccess!-----"
                                        + HexUtil.encodeHexStr(characteristic));
                                doNextSend(times, orderCmd);
                            }

                            @Override
                            public void onFailure(BleException exception) {
                                Logger.e("Send onFail!");
                                doNextSend(times, orderCmd);
                            }
                        });
//                doNextSend(times, orderCmd);

            }

        }
    }

    private void doNextSend(int times, OrderCmd orderCmd) {
        if (dataSplitInfoQueue.peek() != null) {
            handler.sendMessage(obtainMessage(MSG_NORMAL_SEND, times, orderCmd));
//            handler.sendMessageDelayed(obtainMessage(MSG_NORMAL_SEND, times, orderCmd),DEFAULT_INTERVAL_PER_BG_TIME);
        } else {
            // 等待500ms,没有应答则重发
            if (times > 0) {
                handler.sendMessageDelayed(obtainMessage(MSG_REPEAT_SEND, times - 1, orderCmd),
                        DEFAULT_INTERVAL_TIME);
            } else {
                // 发送6001成功或失败加个回调
                if (orderCmd.isNormalCode()) {
                    if (callBackCmd != null) {
                        callBackCmd.onNormalCmdSendEnd();
                    }
                } else {
                    handler.sendMessageDelayed(obtainMessage(MSG_TIME_OUT2, times, orderCmd),
                            DEFAULT_INTERVAL_TIME * 5);
                }
            }
        }
    }

    /**
     * 重置
     */
    public void reSet() {
        if (!dataSplitInfoQueue.isEmpty()) {
            dataSplitInfoQueue.clear();
        }
        if (!dataUnCompleteInfoQueue.isEmpty()) {
            dataUnCompleteInfoQueue.clear();
        }
        handler.removeCallbacksAndMessages(null);
    }

    /**
     * 取消重复发送
     */
    public void cancleRepeat() {
        if (!dataUnCompleteInfoQueue.isEmpty()) {
            dataUnCompleteInfoQueue.clear();
        }
        handler.removeMessages(MSG_REPEAT_SEND);
        handler.removeMessages(MSG_TIME_OUT2);
    }

    /**
     * 取消超时
     */
    public void cancleTimeOut() {
        handler.removeMessages(MSG_TIME_OUT);
        handler.removeMessages(MSG_TIME_OUT2);
    }
}
